#include <iostream>
#include <cstdio>
#include <iomanip>
#include <vector>
#include <set>
#include <algorithm>
#include <string>
#include <cmath>
#include <queue>

using namespace std;

#define mp make_pair
#define pb push_back
#define all(x) x.begin(),x.end()

typedef long long ll;

const int N = 20000;
const int INF = 2.1e9;
struct ed{
	int to;
	int id;
	int w;
	ed() {}
	ed(int to, int id, int w): to(to), id(id), w(w) {}
};
vector<ed> g[N];
int dist[N];
int p[N];
int pe[N];
int cnt[N];
bool used[N];
bool ok[N];

int main(){
	ios_base::sync_with_stdio(false);
	int n, m; cin >> n >> m;
	for (int  i = 0; i < m; ++i){
		int a, b, c;
		cin >> a >> b >> c;
		--a; --b;
		g[a].push_back(ed(b, i, c));
		g[b].push_back(ed(a, i, c));
	}

	priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;
	fill(dist, dist + n, INF);
	fill(p, p + n, -1);
	fill(pe, pe + n, -1);
	dist[0] = 0;
	cnt[0] = 1;
	q.push(make_pair(0, 0));
	while (!q.empty()){
		int v = q.top().second;
		int w = q.top().first;
		q.pop();
		if (used[v]) continue;
		used[v] = true;
		for (int i = 0; i < g[v].size(); ++i){
			const ed& e = g[v][i];
			int newW = w + e.w;
			if (newW < dist[e.to]){
				dist[e.to] = newW;
				cnt[e.to] = cnt[v];
				p[e.to] = v;
				pe[e.to] = e.id;
				q.push(make_pair(newW, e.to));
			} else if (newW == dist[e.to]) {
				cnt[e.to] += cnt[v];
			}
		}
	}
	
	fill(ok, ok + n, true);
	for (int v = 0; v < n; ++v){
		for (int i = 0; i < g[v].size(); ++i){
			const ed& e = g[v][i];
			if (pe[e.to] != e.id && dist[e.to] == dist[v] + e.w) ok[e.to] = false;
		}
	}
	vector<int> ans;
	for (int v = n - 1; v != 0 && ok[v]; v = p[v]){
		if (ok[v]) ans.push_back(pe[v]);
	}
	
	cout << ans.size() << endl;
	for (int i = 0; i < ans.size(); ++i)
		cout << ans[i] + 1 << ' ';
	cout << endl;
	return 0;
}